/*****************************************************************************
 *  @file     实现数据处理接口
 *  @author   Liukh01
 *  @brief    读取数据，保存数据等
 *****************************************************************************/

//-------------------------------------------------------------------
// 头文件
//-------------------------------------------------------------------

#include "date_handel.h"

//-------------------------------------------------------------------
// 双向循环链表头节点
//-------------------------------------------------------------------

struct list_head *film_dcll_head = NULL;
struct list_head *acc_dcll_head = NULL;
struct list_head *order_dcll_head = NULL;
struct list_head *session_dcll_head = NULL;
struct list_head *hall_dcll_head = NULL;

///-------------------------------------------------------------------
// 函数实现
//-------------------------------------------------------------------

void init_all_dcll()
{
    // 创建头节点
    film_dcll_head = malloc(sizeof(struct list_head));
    acc_dcll_head = malloc(sizeof(struct list_head));
    order_dcll_head = malloc(sizeof(struct list_head));
    session_dcll_head = malloc(sizeof(struct list_head));
    hall_dcll_head = malloc(sizeof(struct list_head));

    // 初始化头节点
    INIT_LIST_HEAD(film_dcll_head);
    INIT_LIST_HEAD(acc_dcll_head);
    INIT_LIST_HEAD(order_dcll_head);
    INIT_LIST_HEAD(session_dcll_head);
    INIT_LIST_HEAD(hall_dcll_head);
}

//-------------------------------------------------------------------
// 私有函数
//-------------------------------------------------------------------

char *my_strdup(const char *s)
{
    if (s == NULL)
    {
        return NULL;
    }

    size_t len = strlen(s) + 1;
    char *copy = malloc(len);
    if (copy == NULL)
    {
        return NULL;
    }

    memcpy(copy, s, len);
    return copy;
}

//-------------------------------------------------------------------
// 加载节点函数
//-------------------------------------------------------------------

int load_film_node(void)
{
    FILE *fp = fopen(FILM_DATE_PATH, "r");
    if (fp == NULL)
    {
        printf("<%s>[%d]", __FILE__, __LINE__);
        perror("打开film数据失败");
        return -1;
    }

    // 临时字段用于读取数据
    long film_id;
    char film_name[256] = {0};
    float film_score;
    char film_label[256] = {0};
    time_t film_release_time;
    time_t film_play_time;
    char film_small_photo[256] = {0};
    char film_big_photo[256] = {0};

    while (fscanf(fp, "%ld#%[^#]#%f#%[^#]#%ld#%ld#%[^#]#%[^\n]",
                  &film_id, film_name, &film_score, film_label,
                  &film_release_time, &film_play_time, film_small_photo, film_big_photo) == 8)
    {
        // 创建大结构体节点
        film_dcll *film_dcll_node = malloc(sizeof(film_dcll));
        if (film_dcll_node == NULL)
        {
            printf("<%s>[%d]", __FILE__, __LINE__);
            perror("");
            fclose(fp);
            return -1;
        }

        // 创建数据域
        film_info *film_date = malloc(sizeof(film_info));
        if (film_date == NULL)
        {
            printf("<%s>[%d]", __FILE__, __LINE__);
            perror("");
            free(film_dcll_node);
            fclose(fp);
            return -1;
        }

        // 初始化结构体字段
        film_date->film_id = film_id;
        film_date->film_name = my_strdup(film_name);
        film_date->film_score = film_score;
        film_date->film_label = my_strdup(film_label);
        film_date->film_release_time = film_release_time;
        film_date->film_play_time = film_play_time;
        film_date->film_small_photo = my_strdup(film_small_photo);
        film_date->film_big_photo = my_strdup(film_big_photo);
        // film_date->film_btn = NULL;

        // 检查内存分配是否成功
        if (!film_date->film_name || !film_date->film_label ||
            !film_date->film_small_photo || !film_date->film_big_photo)
        {
            printf("<%s>[%d] 内存分配失败\n", __FILE__, __LINE__);
            // 释放已分配的资源
            free(film_date->film_name);
            free(film_date->film_label);
            free(film_date->film_small_photo);
            free(film_date->film_big_photo);
            free(film_date);
            free(film_dcll_node);
            fclose(fp);
            return -1;
        }

        // 将数据域插入链表
        film_dcll_node->film_info = film_date;
        list_add_tail(&film_dcll_node->list, film_dcll_head);
    }

    fclose(fp);
    return 0;
}

int load_acc_node(void)
{
    FILE *fp = fopen(ACCOUNT_DATE_PATH, "r");
    if (fp == NULL)
    {
        printf("<%s>[%d]", __FILE__, __LINE__);
        perror("打开account数据失败");
        return -1;
    }

    // 临时字段用于读取数据
    long acc_id;
    ACC_TYPE acc_type;
    char acc_phone[256] = {0};
    char acc_id_card[256] = {0};
    time_t acc_time;
    long member_id;
    double acc_balance;

    while (fscanf(fp, "%ld#%d#%[^#]#%[^#]#%ld#%ld#%lf[^\n]",
                  &acc_id, &acc_type, acc_phone, acc_id_card,
                  &acc_time, &member_id, &acc_balance) == 7)
    {
        // 创建大结构体节点
        acc_dcll *acc_dcll_node = malloc(sizeof(acc_dcll));
        if (acc_dcll_node == NULL)
        {
            printf("<%s>[%d]", __FILE__, __LINE__);
            perror("");
            fclose(fp);
            return -1;
        }

        // 创建数据域
        acc_info *acc_date = malloc(sizeof(acc_info));
        if (acc_date == NULL)
        {
            printf("<%s>[%d]", __FILE__, __LINE__);
            perror("");
            free(acc_dcll_node);
            fclose(fp);
            return -1;
        }

        // 初始化结构体字段
        acc_date->acc_id = acc_id;
        acc_date->acc_type = acc_type;
        acc_date->acc_phone = my_strdup(acc_phone);
        acc_date->acc_id_card = my_strdup(acc_id_card);
        acc_date->acc_time = acc_time;
        acc_date->member_id = member_id;
        acc_date->acc_balance = acc_balance;

        // 检查内存分配是否成功
        if (!acc_date->acc_phone || !acc_date->acc_id_card)
        {
            printf("<%s>[%d] 内存分配失败\n", __FILE__, __LINE__);
            // 释放已分配的资源
            free(acc_date->acc_phone);
            free(acc_date->acc_id_card);
            free(acc_date);
            free(acc_dcll_node);
            fclose(fp);
            return -1;
        }

        // 将数据域插入链表
        acc_dcll_node->acc_info = acc_date;
        list_add_tail(&acc_dcll_node->list, acc_dcll_head);
    }

    fclose(fp);
    return 0;
}

int load_order_node(void)
{
    FILE *fp = fopen(ORDER_DATE_PATH, "r");
    if (fp == NULL)
    {
        printf("<%s>[%d]", __FILE__, __LINE__);
        perror("打开order数据失败");
        return -1;
    }

    // 临时字段用于读取数据
    long order_id;
    long acc_id;
    long session_id;
    time_t order_time;
    double order_price;

    while (fscanf(fp, "%ld#%ld#%ld#%ld#%lf[^\n]",
                  &order_id, &acc_id, &session_id, &order_time, &order_price) == 5)
    {
        // 创建大结构体节点
        order_dcll *order_dcll_node = malloc(sizeof(order_dcll));
        if (order_dcll_node == NULL)
        {
            printf("<%s>[%d]", __FILE__, __LINE__);
            perror("");
            fclose(fp);
            return -1;
        }

        // 创建数据域
        order_info *order_date = malloc(sizeof(order_info));
        if (order_date == NULL)
        {
            printf("<%s>[%d]", __FILE__, __LINE__);
            perror("");
            free(order_dcll_node);
            fclose(fp);
            return -1;
        }

        // 初始化结构体字段
        order_date->order_id = order_id;
        order_date->acc_id = acc_id;
        order_date->session_id = session_id;
        order_date->order_time = order_time;
        order_date->order_price = order_price;

        // 将数据域插入链表
        order_dcll_node->order_info = order_date;
        list_add_tail(&order_dcll_node->list, order_dcll_head);
    }

    fclose(fp);
    return 0;
}

int load_session_node(void)
{
    FILE *fp = fopen(SESSION_DATE_PATH, "r");
    if (fp == NULL)
    {
        printf("<%s>[%d]", __FILE__, __LINE__);
        perror("打开session数据失败");
        return -1;
    }

    // 临时字段用于读取数据
    long session_id;
    long film_id;
    long hall_id;
    double session_price;
    time_t session_time;

    while (fscanf(fp, "%ld#%ld#%ld#%lf#%ld[^\n]", &session_id, &film_id, &hall_id, &session_price, &session_time) == 5)
    {
        // 创建大结构体节点
        session_dcll *session_dcll_node = malloc(sizeof(session_dcll));
        if (session_dcll_node == NULL)
        {
            printf("<%s>[%d]", __FILE__, __LINE__);
            perror("");
            fclose(fp);
            return -1;
        }

        // 创建数据域
        session_info *session_date = malloc(sizeof(session_info));
        if (session_date == NULL)
        {
            printf("<%s>[%d]", __FILE__, __LINE__);
            perror("");
            free(session_dcll_node);
            fclose(fp);
            return -1;
        }

        // 初始化结构体字段
        session_date->session_id = session_id;
        session_date->film_id = film_id;
        session_date->hall_id = hall_id;
        session_date->session_price = session_price;
        session_date->session_time = session_time;

        // 将数据域插入链表
        session_dcll_node->session_info = session_date;
        list_add_tail(&session_dcll_node->list, session_dcll_head);
    }

    fclose(fp);
    return 0;
}

int load_hall_node(void)
{
    FILE *fp = fopen(HALL_DATE_PATH, "r");
    if (fp == NULL)
    {
        printf("<%s>[%d]", __FILE__, __LINE__);
        perror("打开hall数据失败");
        return -1;
    }

    // 临时字段用于读取数据
    long hall_id;
    char hall_name[256] = {0};

    while (fscanf(fp, "%ld#%[^\n]", &hall_id, hall_name) == 2)
    {
        // 创建大结构体节点
        hall_dcll *hall_dcll_node = malloc(sizeof(hall_dcll));
        if (hall_dcll_node == NULL)
        {
            printf("<%s>[%d]", __FILE__, __LINE__);
            perror("");
            fclose(fp);
            return -1;
        }

        // 创建数据域
        hall_info *hall_date = malloc(sizeof(hall_info));
        if (hall_date == NULL)
        {
            printf("<%s>[%d]", __FILE__, __LINE__);
            perror("");
            free(hall_dcll_node);
            fclose(fp);
            return -1;
        }

        // 初始化结构体字段
        hall_date->hall_id = hall_id;
        hall_date->hall_name = my_strdup(hall_name);

        // 检查内存分配是否成功
        if (!hall_date->hall_name)
        {
            printf("<%s>[%d] 内存分配失败\n", __FILE__, __LINE__);
            // 释放已分配的资源
            free(hall_date->hall_name);
            free(hall_date);
            free(hall_dcll_node);
            fclose(fp);
            return -1;
        }

        // 将数据域插入链表
        hall_dcll_node->hall_info = hall_date;
        list_add_tail(&hall_dcll_node->list, hall_dcll_head);
    }

    fclose(fp);
    return 0;
}

//-------------------------------------------------------------------
// 保存重要节点信息
//-------------------------------------------------------------------

int save_acc_node(void)
{
    // 判断链表是否为空
    if (list_empty(acc_dcll_head))
    {
        printf("<%s>[%d] 账号节点为空\n", __FILE__, __LINE__);
        return -1;
    }

    // 打开文件
    FILE *fp = fopen(ACCOUNT_DATE_PATH, "w");
    if (fp == NULL)
    {
        printf("<%s>[%d]", __FILE__, __LINE__);
        perror("打开账号数据文件失败");
        return -1;
    }

    acc_dcll *pos;
    list_for_each_entry(pos, acc_dcll_head, list)
    {
        // 判断数据内容是否为空
        if (pos->acc_info == NULL)
        {
            printf("<%s>[%d] 账号数据为空\n", __FILE__, __LINE__);
            continue;
        }

        // 保存账号数据内容
        fprintf(fp, "%ld#%d#%s#%s#%ld#%ld#%lf\n",
                pos->acc_info->acc_id,
                pos->acc_info->acc_type,
                pos->acc_info->acc_phone,
                pos->acc_info->acc_id_card,
                pos->acc_info->acc_time,
                pos->acc_info->member_id,
                pos->acc_info->acc_balance);
    }

    fclose(fp);
    return 0;
}

int save_order_node(void)
{
    // 判断链表是否为空
    if (list_empty(order_dcll_head))
    {
        printf("<%s>[%d] 订单节点为空\n", __FILE__, __LINE__);
        return -1;
    }

    // 打开文件
    FILE *fp = fopen(ORDER_DATE_PATH, "w");
    if (fp == NULL)
    {
        printf("<%s>[%d]", __FILE__, __LINE__);
        perror("打开order数据文件失败");
        return -1;
    }

    order_dcll *pos;
    list_for_each_entry(pos, order_dcll_head, list)
    {
        // 判断数据内容是否为空
        if (pos->order_info == NULL)
        {
            printf("<%s>[%d] 订单数据为空\n", __FILE__, __LINE__);
            continue;
        }

        // 保存订单数据内容
        fprintf(fp, "%ld#%ld#%ld#%ld#%lf\n",
                pos->order_info->order_id,
                pos->order_info->acc_id,
                pos->order_info->session_id,
                pos->order_info->order_time,
                pos->order_info->order_price);
    }

    fclose(fp);
    return 0;
}

//-------------------------------------------------------------------
// 追加节点信息
//-------------------------------------------------------------------

int add_acc_node(char *phone, char *id_card, ACC_TYPE type)
{
    // 创建大结构体节点
    acc_dcll *acc_dcll_node = malloc(sizeof(acc_dcll));
    if (acc_dcll_node == NULL)
    {
        printf("<%s>[%d]", __FILE__, __LINE__);
        perror("");
        return -1;
    }

    // 创建数据域
    acc_info *acc_date = malloc(sizeof(acc_info));
    if (acc_date == NULL)
    {
        printf("<%s>[%d]", __FILE__, __LINE__);
        perror("");
        free(acc_dcll_node);
        return -1;
    }

    // 获取最大的账号ID和会员ID
    long max_acc_id = 0;
    long max_member_id = 0;

    // 从后往前遍历链表
    if (!list_empty(acc_dcll_head))
    {
        acc_dcll *pos;
        list_for_each_entry_reverse(pos, acc_dcll_head, list)
        {
            if (pos->acc_info != NULL)
            {
                if (pos->acc_info->acc_id > max_acc_id)
                {
                    max_acc_id = pos->acc_info->acc_id;
                }
                if (pos->acc_info->member_id > max_member_id)
                {
                    max_member_id = pos->acc_info->member_id;
                }
            }
        }
    }

    // 初始化结构体字段
    acc_date->acc_id = max_acc_id + 1; // 账号ID自增
    acc_date->acc_type = type;
    acc_date->acc_phone = my_strdup(phone);
    acc_date->acc_id_card = my_strdup(id_card);
    acc_date->acc_time = time(NULL);         // 获取系统时间
    acc_date->member_id = max_member_id + 1; // 会员ID自增
    acc_date->acc_balance = 0.0;             // 余额初始为0

    // 检查内存分配是否成功
    if (!acc_date->acc_phone || !acc_date->acc_id_card)
    {
        printf("<%s>[%d] 内存分配失败\n", __FILE__, __LINE__);
        // 释放已分配的资源
        free(acc_date->acc_phone);
        free(acc_date->acc_id_card);
        free(acc_date);
        free(acc_dcll_node);
        return -1;
    }

    // 将数据域插入链表
    acc_dcll_node->acc_info = acc_date;
    list_add_tail(&acc_dcll_node->list, acc_dcll_head);

    char *tmp_option = NULL;
    switch (type)
    {
    case SUPER_MEMBERS:
        tmp_option = "超级会员";
        break;
    case HIGH_LEVEL_MEMBERS:
        tmp_option = "高级会员";
        break;
    case REGULAR_MEMBERS:
        tmp_option = "普通会员";
        break;
    }

    char id_str[7]; // 6位字符串 + '\0'
    sprintf(id_str, "%06ld", acc_date->member_id);
    printf("会员编号：%s, 电话: %s, 身份证: %s, 等级: %s\n", id_str, phone, id_card, tmp_option);

    // 保存账号数据到文件
    save_acc_node();

    return 0;
}

int add_order_node(long acc_id, long session_id, double price)
{
    // 创建大结构体节点
    order_dcll *order_dcll_node = malloc(sizeof(order_dcll));
    if (order_dcll_node == NULL)
    {
        printf("<%s>[%d]", __FILE__, __LINE__);
        perror("");
        return -1;
    }

    // 创建数据域
    order_info *order_date = malloc(sizeof(order_info));
    if (order_date == NULL)
    {
        printf("<%s>[%d]", __FILE__, __LINE__);
        perror("");
        free(order_dcll_node);
        return -1;
    }

    // 获取最大的订单ID
    long max_order_id = 0;

    // 从后往前遍历链表
    if (!list_empty(order_dcll_head))
    {
        order_dcll *pos;
        list_for_each_entry_reverse(pos, order_dcll_head, list)
        {
            if (pos->order_info != NULL && pos->order_info->order_id > max_order_id)
            {
                max_order_id = pos->order_info->order_id;
            }
        }
    }

    // 初始化结构体字段
    order_date->order_id = max_order_id + 1; // 订单ID自增
    order_date->acc_id = acc_id;
    order_date->session_id = session_id;
    order_date->order_time = time(NULL); // 获取系统时间
    order_date->order_price = price;

    // 将数据域插入链表
    order_dcll_node->order_info = order_date;
    list_add_tail(&order_dcll_node->list, order_dcll_head);

    // 打印订单编号
    char tmp_str[17]; // 16位字符串 + '\0'
    sprintf(tmp_str, "%016ld", order_date->order_id);
    printf("订单编号：%s\n", tmp_str);

    // 保存订单数据到文件
    save_order_node();

    return 0;
}

//-------------------------------------------------------------------
// 系统数据操作
//-------------------------------------------------------------------

void load_system_date(void)
{
    init_all_dcll();

    load_film_node();
    load_acc_node();
    load_order_node();
    load_session_node();
    load_hall_node();
}